import exception.RedefineClassesUnsupportedException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import utils.ClassFileUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.lang.instrument.ClassDefinition;
import java.lang.instrument.Instrumentation;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class HotUpdateAgent {
    private Instrumentation inst;
    private static Log log = LogFactory.getLog(HotUpdateAgent.class);
    public static void agentmain(String agentArgs, Instrumentation inst) {
        if (!inst.isRedefineClassesSupported()) {
            throw new RedefineClassesUnsupportedException();
        }
        log.info("hot update start.");
        try {
            String[] args = agentArgs.split(";");
            String path = args[0];
            String[] fileNames = args[1].split(",");
            List<String> nameList = Arrays.asList(fileNames);
            log.info("hot updating class : " + nameList);
            List<ClassDefinition> definitions = new ArrayList<>();
            for (String fileName : fileNames) {
                File file = new File(path + File.separator + fileName);
                if (!file.exists()) {
                    throw new FileNotFoundException();
                }
                byte[] bytes = new byte[(int) file.length()];
                new FileInputStream(file).read(bytes);
                definitions.add(new ClassDefinition(Class.forName(ClassFileUtils.getClassName(bytes)), bytes));
            }
            if (!definitions.isEmpty()) {
                ClassDefinition[] definitionsArray = definitions.stream().toArray(ClassDefinition[]::new);
                inst.redefineClasses(definitionsArray);
            }
            log.info(nameList + " hot update success.");
        } catch (Exception e) {
            log.error("hot update error:", e);
        }
    }

    public static void main(String[] args) {
        String arg = "/User/codeist/work/java/path;Speaker.class,Dog.class,";
        String[] str = arg.split(";");
        String path = str[0];
        String file = str[1];
        String[] fileNames = file.split(",");
        List<String> list = Arrays.asList(fileNames);
        System.out.println(list);
    }
    public Instrumentation getInst() {
        return inst;
    }
}
